import base64
import json

from datetime import datetime

from django.http import HttpResponse
from django.http import JsonResponse
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.generics import CreateAPIView, ListAPIView, RetrieveAPIView, \
    UpdateAPIView
from rest_framework.mixins import CreateModelMixin
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework_jwt.settings import api_settings

from celery_comsumer.process.tasks import triget_process

from mini_api.models import PcDevice, Company, Process, User, WXmini_Auth, Job
from mini_api.permissions import IsOwnerOrReadOnly
from mini_api.serializers import PcDeviceSerializer, CompanySerializer, ProcessSerializer, RPAUserSerializer, \
    ProcessCMDSerializer, \
    JobListSerializer
from mini_api.utils import WXOpenid


from utils.cmd_handle import get_celery_result



def index(request):
    return HttpResponse('')

class RegisterView(CreateAPIView, ListAPIView):
    queryset = User.objects.all()
    serializer_class = RPAUserSerializer


class RPAUserView(APIView):
    def get(self, request):

        params = request.data
        code = params.get('code')
        if code is None:
            return JsonResponse(data={"code": 3, "msg": "未获取到微信 js code"})

        openid, session_key = WXOpenid.get_open_id(code)

        # 判断openid注册
        try:
            we_auth = WXmini_Auth.objects.get(open_id=openid)
        except:
            # 未注册
            # 返回code为0
            return JsonResponse(data={"code": 0, 'msg': "该用户不存在"}, status=status.HTTP_204_NO_CONTENT)
        else:
            # 获取对应用户信息
            user = we_auth.user

            if user.is_active == 1:
                # is_active 为1 则为未激活
                return JsonResponse(data={"code": 1, "msg": "请联系管理员激活账号"}, status=status.HTTP_204_NO_CONTENT)

            # 生成JWT token值
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            response = Response(
                {
                    'user_id': user.id,
                    'username': user.username,
                    'token': token
                }
            )
            return response

            # 获取用户信息返回


class PcDeviceViewSet(ModelViewSet):
    serializer_class = PcDeviceSerializer
    permission_classes = [IsOwnerOrReadOnly]
    queryset = PcDevice.objects.all()

    # def post(self, request):
    #     return self.create(request)

class CompanyViewSet(ModelViewSet):
    queryset = Company.objects.all()
    serializer_class = CompanySerializer
    permission_classes = [AllowAny]




class ProcessViewSet(ModelViewSet):
    queryset = Process.objects.all()
    serializer_class = ProcessSerializer
    permission_classes = [AllowAny]

    def get_serializer_class(self):
        if self.action == 'process_cmd':
            return ProcessCMDSerializer
        else:
            return ProcessSerializer


    @action(methods=["post",],detail=False)
    def process_cmd(self,request):
        param = request.data

        serializer = self.get_serializer(data=param)

        serializer.is_valid(raise_exception=True)
        v_param = serializer.validated_data

        machine_code = v_param.get('machine_code_token').machine_code

        # 获取流程路径和RPA类型
        path = v_param.get('process_id').process_path
        rpa_type = v_param.get("process_id").process_type

        # 执行RPA流程
        c_result = triget_process.delay(machine_code, path, rpa_type)

        # 获取执行结果，用来发邮件或者短信
        celery_result = get_celery_result(c_result.id)

        now_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 创建新记录
        new_job = {"process": v_param.get('process_id'), 'start_time': now_time, "status": celery_result,
                   'celery_key': c_result}

        # 添加到记录
        insert_id = Job.objects.create(**new_job)

        # 修改数据库结果

        return Response({'code': "已触发"})






class JobListView(APIView):
    permission_classes = (AllowAny,)

    def get(self, request):
        # 获取用户
        # 根据用户id获取对应process_id
        # 根据process_id获取job
        job_data = Job.objects.all()
        # 获取job记录中为pending的数据
        pending_job_key = []
        for job_item in job_data:
            if job_item.status == 'PENDING':
                pending_job_key.append("celery-task-meta-{}".format(job_item.celery_key))

        # 查询job记录中为pending的数据结果
        redis_conn = get_redis_connection('celery_result')
        redis_conn_pipe = redis_conn.pipeline()
        for key in pending_job_key:
            redis_conn_pipe.get(key)

        r_data_bytes_list = redis_conn_pipe.execute()
        r_data_list = []
        if r_data_bytes_list is not None:
            for item in r_data_bytes_list:
                if item:
                    r_data_list.append(json.loads(item))
                    # r_data_list = [json.loads(item) for item in r_data_bytes_list]

        update_dict = dict()
        for item in r_data_list:
            if item.get(status) != "PENDING":
                # 更新状态
                job_obj = Job.objects.get(celery_key=item.get('task_id'))
                job_obj.status = item.get("status")
                job_obj.save()
                # 删除redis中对应的key
                redis_conn.delete("celery-task-meta-{}".format(item.get('task_id')))

        job_data = Job.objects.all()

        serializer = JobListSerializer(job_data, many=True)

        return Response(data=serializer.data)


class RobotStatusView(APIView):
    permission_classes = [AllowAny, ]

    def post(self, request):
        try:
            code = request.data.get("code")
            redis_conn = get_redis_connection('robot_status')
            redis_conn.set("online-{}".format(code), "333", ex=60)
            return Response({'success': 1})
        except Exception as e:
            return Response({'success': 0})
